<?php
declare (strict_types = 1);

namespace app\common\command;

use app\common\model\user\Assignment;
use app\common\model\user\RolePermission;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\Output;
use app\common\model\user\Permission as PermissionModel;
use think\Exception;
use think\facade\Db;

class Permission extends Command
{

    //角色
    const ROLE_ADMIN = '管理员';
    const ROLE_AUTHOR = '作者';

    protected function configure()
    {
        // 指令配置
        $this->setName('permission')
            ->addArgument('action', Argument::OPTIONAL, "[init | enabled | disabled] set permission")
            ->setDescription('permission init command');
    }

    protected function execute(Input $input, Output $output)
    {
        // 指令输出
        $action = $input->getArgument('action') ?: 'init';
        $action = strtolower($action);

        switch ($action){
            case 'init':
                $this->init($output);
                break;
            case 'enabled':
                $this->enabled($output);
                break;
            case 'disabled':
                $this->disabled($output);
                break;
            default:
                $output->writeln('action param error.');
                break;
        }

    }

    /**
     * 权限初始化
     * @param Output $output
     * @return bool
     */
    private function init(Output $output){

        Db::transaction(function () use ($output) {
            //清空数据
            $this->clearAll();

            //保存路由
            $this->saveRoute();

            //保存角色
            $roleRes = $this->saveRole()->toArray();

            //创建角色路由关系
            $relate = $this->createRelate($roleRes, $this->getInitRouteIds());

            //保存关联数据
            $this->saveRelate($relate);
        });
        //初始化完成
        $output->writeln('Permission initialization completed');
        return true;
    }

    /**
     * 清空权限角色和关联数据
     */
    private function clearAll(){
        // 无条件删除所有数据
        PermissionModel::where([])->delete(true);
        RolePermission::where([])->delete(true);
        Assignment::where([])->delete(true);
    }

    /**
     * 添加所有权限路由
     * @return bool
     */
    private function saveRoute(){
        $path = app()->getBasePath(). 'admin'. DIRECTORY_SEPARATOR . 'controller';
        $all = PermissionModel::getNotAdded($path);

        //保存路由
        return PermissionModel::saveRoute($all);

    }

    /**
     * 添加初始化角色 管理员及作者
     * @return \think\Collection
     * @throws \Exception
     */
    private function saveRole(){

        $data = [
            ['name'=>static::ROLE_ADMIN,'type'=>PermissionModel::TYPE_ROLE,'rule'=>PermissionModel::RULE_ROLE_DISABLED,'desc'=>'管理员'],
            ['name'=>static::ROLE_AUTHOR,'type'=>PermissionModel::TYPE_ROLE,'rule'=>PermissionModel::RULE_ROLE_ENABLED,'desc'=>'作者'],
        ];
        return (new PermissionModel())->saveAll($data);
    }

    /**
     * 创建角色权限关联数据
     * @param array $roles [
     *      1 => ['name'=>'管理员','type'=>2,'rule'=>2],
     *      2 => ['name'=>'作者','type'=>2,'rule'=>2]
     * ] #角色数据
     * @param array $routes [
     *      '管理员' => ['route1ID', 'route2ID', 'route3ID'],
     *      '作者' => ['route1ID', 'route2ID', 'route3ID']
     * ] #需关联的权限路由
     *
     * @return array
     */
    private function createRelate(array $roles, array $routes){

        $ret = [];
        foreach ($roles as $k => $v){
            if (array_key_exists($v['name'], $routes)){
                foreach ($routes[$v['name']] as $routeID){
                    $ret[] = ['permission_id' => $routeID, 'role_id'=>$v['id']];
                }
            }
        }
        return $ret;
    }

    /**
     * #根据配置的角色初始化路由获取路由id
     * @return array
     * @throws Exception
     */
    private function getInitRouteIds(){
        $ret = [];
        $data = config('permission.init');
        if (empty($data[static::ROLE_ADMIN]) || empty($data[static::ROLE_AUTHOR])){
            throw new Exception('app.permission required');
        }

        $ret[static::ROLE_ADMIN] = PermissionModel::where([
            ['type', '=', PermissionModel::TYPE_PERMISSION],
            ['name', 'in', $data[static::ROLE_ADMIN]]
        ])->column('id');
        $ret[static::ROLE_AUTHOR] = PermissionModel::where([
            ['type', '=', PermissionModel::TYPE_PERMISSION],
            ['name', 'in', $data[static::ROLE_AUTHOR]]
        ])->column('id');

        return $ret;
    }

    /**
     * 保存角色和权限路由的关系
     * @param array $data
     * @return \think\Collection
     * @throws \Exception
     */
    private function saveRelate(array $data){

        return (new RolePermission())->saveAll($data);
    }















    /**
     * 权限激活
     * @param Output $output
     */
    private function enabled(Output $output){
        $output->writeln('permission enabled finish.');
    }
    /**
     * 权限关闭
     * @param Output $output
     */
    private function disabled(Output $output){
        $output->writeln('permission disabled finish.');
    }

}
